package com.example.demo.config.security;

import com.example.demo.entity.member.User;
import com.example.demo.entity.sysuser.SysUser;
import com.example.demo.service.SysUser.SysSecurityService;
import com.example.demo.service.member.UserSecurityService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author longzhonghua
 * @data 2018/11/04 22:30
 */
@Configuration//指定为配置类
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class HttpSecurityConfig  {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 后台用户安全配置-内部类
     */
    @Configuration
    @Order(1)
    public static class AdminSecurityConfig extends WebSecurityConfigurerAdapter {
        @Bean
        /**
         * 管理员登录查询的service，实现了UserDetailsService接口
         */
        public UserDetailsService sysSecurityService() {
            return new  SysSecurityService();
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(sysSecurityService());
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/admin/**")//后台安全配置开始
                    .csrf().disable()//禁用csrf（简单，不安全）
                    .headers().frameOptions().sameOrigin()
                    .and()
                    .formLogin()//可以自定义页面，自定义控制器路径，但不能使用自己的登录控制器
                    .loginPage("/admin/login")//控制器名字
                    .loginProcessingUrl("/admin/doLogin")
                    .successHandler(new AuthenticationSuccessHandler() {
                        //兼容自定义权限控制的首页代码
                        //否则首页需要使用thymeleaf和security扩展的语法在页面显示
                        @Override
                        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                            SysUser sysUser=(SysUser) authentication.getPrincipal();
                            request.getSession().setAttribute("sysUser",sysUser);
                            response.sendRedirect(request.getContextPath() + "/admin/index");
                        }
                    })
                    .permitAll()//所有人都可以访问
                    .and()
                    .logout()//注销也是由security提供的，只能定义路径
                    .logoutUrl("/admin/logout")//控制器名字
                    .logoutSuccessUrl("/admin/login")//控制器名字
                    .permitAll()
                    .and()
                    .authorizeRequests()
//                    .antMatchers("/admin/index").authenticated()///admin/index登录后可以访问
                    .antMatchers("/admin/index").hasRole("ADMIN")//跟网站普通用户区别，所有后台管理员都有共同角色ADMIN
                    .antMatchers("/admin/**")
                    .access("@rbacService.hasPermission(request,authentication)");
        }
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/*.ico")
                    .antMatchers("/css/**")
                    .antMatchers("/js/**")
                    .antMatchers("/layui/**");

        }
    }

    /**
     * 普通用户安全配置
     */
    @Configuration
    @Order(2)
    public static class UserSecurityConfig extends WebSecurityConfigurerAdapter {
        /**
         * 普通用户登录的service，也实现了UserDetailService接口，查询的是普通用户表
         * 方法名字要跟上面的方法名字不一样
         * @return
         */
        @Bean
        public UserDetailsService userSecurityService() {
            return new UserSecurityService();
        }
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userSecurityService());
        }
        @Override
        protected void configure(HttpSecurity http) throws Exception {
//            http.requestMatchers().
            http.formLogin()//可以自定义页面，自定义控制器路径，但不能使用自己的登录控制器
                    .loginPage("/user/login")
                    .loginProcessingUrl("/user/doLogin")
                    .usernameParameter("account")
                    .successHandler(new AuthenticationSuccessHandler() {
                        @Override
                        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                            User user=(User) authentication.getPrincipal();
                            request.getSession().setAttribute("loginUser",user);
                            response.sendRedirect(request.getContextPath() + "/home");
                        }
                    })
                    .permitAll()//所有人都可以访问
                    .and()
                    .logout()//注销也是由security提供的，只能定义路径
                    .logoutUrl("/user/logout")//控制器名字
                    .logoutSuccessUrl("/home")//控制器名字
                    .permitAll()
                    .and()
                    .authorizeRequests()
                    .antMatchers("/pay/wxpay/notify",
                            "/home","/user/**","/product/**","/web/**",
                            "/seckill/seckillListByCache",
                            "/seckill/getLoginUserId",
                            "/pay/alipay/notify",
                            "/pay/alipay/return")
                    .permitAll()
                    .antMatchers("/cart/**","/pay/**"
                            ,"/order/**").hasRole("USER")//购车车需要普通用户登录后访问
                    .and()
                    .csrf().disable()
                    .headers().frameOptions().sameOrigin()
                    ;


        }
    }



}